package com.redijedi.tapestry5.components;

import org.apache.tapestry.Asset;
import org.apache.tapestry.ComponentResources;
import org.apache.tapestry.Field;
import org.apache.tapestry.PageRenderSupport;
import org.apache.tapestry.annotations.Environmental;
import org.apache.tapestry.annotations.Inject;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.annotations.Path;
import org.apache.tapestry.annotations.SetupRender;

/**
 * @author torr
 * 
 */
public class Rating implements Field {

	@Inject
	private ComponentResources _resources;

	@Environmental
	private PageRenderSupport _renderSupport;

	@Parameter(required = false)
	private boolean _showFirstValue = false;

	@Parameter(required = false, value = "true")
	private boolean _useHover = false;

	@Parameter(required = true)
	private Object _value;

	@Parameter(required = true, defaultPrefix = "literal")
	private String _source;

	@Parameter(required = false)
	private Asset _selectedImage;

	@Parameter(required = false)
	private Asset _unselectedImage;

	@Parameter(required = false)
	private Asset _hoverImage;

	@Parameter(required = false, defaultPrefix = "literal")
	private String _label;

	private String[] _splitSourceValues;

	private String _loopValue;

	@Inject
	@Path("rating.js")
	private Asset _imageSwitcherJs;

	@Inject
	@Path("rating_events.js")
	private Asset _bodyLoaderJs;

	@Inject
	@Path("rating_default_selected.gif")
	private Asset _defaultSelectedImage;

	@Inject
	@Path("rating_default_unselected.gif")
	private Asset _defaultUnselectedImage;

	@Inject
	@Path("rating_default_hover.gif")
	private Asset _defaultHoverImage;

	/**
	 * Returns a class name String indicating whether or not the current item
	 * should be displayed.
	 * 
	 * @return
	 */
	public String getItemDisplayClass() {
		if (!_showFirstValue && _loopValue == getSplitSource()[0]) {
			return "t-invisible";
		} else {
			return "";
		}
	}

	/**
	 * Returns the correct image (unselected or selected) based on the value of
	 * the current loop iteration versus the value of this component. For
	 * example, if the value is 3, all loop iterations up to and including 3
	 * will be displayed with the selectedImage while any options above this
	 * value will display the unselectedImage.
	 * 
	 * @return
	 */
	public Asset getItemImage() {
		if (Double.compare(convertValueToDouble(_loopValue),
				convertValueToDouble(_value)) < 0) {
			return getSelectedImage();
		} else {
			return getUnselectedImage();
		}
	}

	/**
	 * Ensures that the value is in the form of a string. TODO this may be
	 * required due to a bug in T5.
	 * 
	 * @return
	 */
	public String getConvertedValue() {
		return convertValueToString(_value);
	}

	private String convertValueToString(Object value) {
		if (_value instanceof String) {
			return (String) _value;
		} else if (_value instanceof Integer) {
			return String.valueOf((Integer) _value);
		}
		if (_value instanceof Long) {
			return String.valueOf((Long) _value);
		}
		if (_value instanceof Double) {
			return String.valueOf((Double) _value);
		} else {
			return null;
		}
	}

	private Double convertValueToDouble(Object value) {
		if (_value instanceof String) {
			return Double.valueOf((String) _value);
		} else if (_value instanceof Integer) {
			return Double.valueOf(String.valueOf((Integer) _value));
		}
		if (_value instanceof Long) {
			return Double.valueOf(String.valueOf((Long) _value));
		}
		if (_value instanceof Double) {
			return (Double) _value;
		} else {
			return null;
		}
	}

	/**
	 * Returns a String array of the comma separated String passed into the
	 * source parameter.
	 * 
	 * @return
	 */
	public String[] getSplitSource() {
		if (_splitSourceValues == null) {
			_splitSourceValues = _source.split(",");
		}
		return _splitSourceValues;
	}

	/**
	 * Convenience method returning the count of the source elements.
	 * 
	 * @return
	 */
	public int getSourceCount() {
		return getSplitSource().length;
	}

	public boolean getIsFirstItem() {
		return _loopValue.equals(getSplitSource()[0]);
	}

	/**
	 * @return the boolean indicating whether to use the hover image.
	 */
	public boolean getUseHover() {
		return _useHover;
	}

	/**
	 * @param loopValue
	 *            the loopValue to set
	 */
	public void setLoopValue(String loopValue) {
		this._loopValue = loopValue;
	}

	/**
	 * @return the loopValue
	 */
	public String getLoopValue() {
		if (_loopValue == null) {
			_loopValue = getSplitSource()[0];
		}
		return _loopValue;
	}

	/**
	 * Returns the label String associated with the current loopValue.
	 * 
	 * @return
	 */
	public String getRadioLabel() {
		return String.valueOf(_loopValue);
	}

	/**
	 * Returns the image representing an unselected value.
	 * 
	 * @return
	 */
	public Asset getUnselectedImage() {
		if (_unselectedImage == null) {
			return _defaultUnselectedImage;
		} else {
			return _unselectedImage;
		}
	}

	/**
	 * Returns the image representing a selected value.
	 * 
	 * @return
	 */
	public Asset getSelectedImage() {
		if (_selectedImage == null) {
			return _defaultSelectedImage;
		} else {
			return _selectedImage;
		}
	}

	/**
	 * Returns the image to use while hovering over a value.
	 * 
	 * @return
	 */
	public Asset getHoverImage() {
		if (_hoverImage == null) {
			return _defaultHoverImage;
		} else {
			return _hoverImage;
		}
	}

	public String getId() {
		return _resources.getId();
	}

	/*
	 * Field Methods
	 */

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tapestry.Field#getElementName()
	 */
	public String getElementName() {
		return "div";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tapestry.Field#isDisabled()
	 */
	public boolean isDisabled() {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tapestry.ClientElement#getClientId()
	 */
	public String getClientId() {
		return getId();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.tapestry.Field#getLabel()
	 */
	public String getLabel() {
		if (_label == null)
			return getId() + " Label";
		else
			return _label;
	}

	/**
	 * Manages adding the correct JS includes into the page head section.
	 */
	@SetupRender
	void manageJavascript() {
		_renderSupport.addScriptLink(_bodyLoaderJs);
		_renderSupport.addScriptLink(_imageSwitcherJs);
	}

}
